#include <Windows.h>
#include <string.h>
#include <stdio.h>
#include "HashTable.h"
#include "DynamicCodeLoader.h"


//



static const char *STR_FreePtrAPI = "FreePtr";
static const char *STR_InitAPI = "ModuleInit";
static const char *STR_SleepAPI = "ModuleSleep";
static const char * STR_ExitAPI = "ModuleExit";
static const char *STR_WndProccess = "WndProc";

extern "C"
{
 extern	void sendMessageSwf(const char* name, const char* value);
}

CDCodeLoader::CDCodeLoader()
:m_hModule(NULL), m_modulePath(NULL), m_apiHashTable(NULL), m_apiNameList(NULL) , m_moduleFreeAPI(NULL),
m_moduleInitAPI(NULL), m_moduleSleepAPI(NULL), m_moduleExitAPI(NULL), m_moduleWndProcAPI(NULL)
{
}

CDCodeLoader::~CDCodeLoader()
{
	ReleaseModule();
}

void CDCodeLoader::ReleaseModule()
{
	if (m_hModule)
	{
		if (m_moduleExitAPI)
		{
			m_moduleExitAPI();
		}
		FreeLibrary((HMODULE)m_hModule);
	}
	if (m_modulePath)
	{
		free(m_modulePath);
		m_modulePath = NULL;
	}
	if (m_apiNameList)
	{
		for (int i = 0; i < m_apiNum; ++ i)
		{
			if (m_apiNameList[i])
			{
				free(m_apiNameList[i]);
			}
		}
		delete [] m_apiNameList;
		m_apiNameList = NULL;
	}
	if (m_apiHashTable)
	{
		HT_table_free((struct HT_table*)m_apiHashTable);
		m_apiHashTable = NULL;
	}
	m_moduleFreeAPI = NULL;
	m_moduleInitAPI = NULL;
	m_moduleSleepAPI = NULL;
	m_moduleExitAPI = NULL;
}

int CDCodeLoader::LoadAPI(char **apilist, int apinum)
{
	m_apiNameList = new char*[apinum];
	m_apiNum = apinum;
	struct HT_table* ht = HT_kchar_table_new(apinum, NULL, NULL);
	for (int i = 0; i < apinum; ++ i)
	{
		m_apiNameList[i] = _strdup(apilist[i]);
#ifdef UNDER_CE
		FARPROC apiAddr = GetProcAddressA((HMODULE)m_hModule, m_apiNameList[i]);
#else
		FARPROC apiAddr = GetProcAddress((HMODULE)m_hModule, m_apiNameList[i]);
#endif
		HT_table_insert(ht, m_apiNameList[i], apiAddr);
	}
	m_apiHashTable = (void*)ht;
	return 0;
}

bool CDCodeLoader::LoadModule(char *path, char **apilist, int apinum)
{
	ReleaseModule();
	if (path)
	{
		WCHAR wpath[268] = {0};
		size_t len=260;
		UTF8to16(path, (int)strlen(path), wpath, &len);
		m_hModule = (void*)LoadLibrary(wpath);
		if (m_hModule)
		{
			m_modulePath = _strdup(path);
#ifdef UNDER_CE
			m_moduleFreeAPI = (EXT_MODULE_FREE_PTR)GetProcAddressA((HMODULE)m_hModule, STR_FreePtrAPI);
			m_moduleInitAPI = (EXT_MODULE_ON_INIT)GetProcAddressA((HMODULE)m_hModule, STR_InitAPI);
			m_moduleSleepAPI = (EXT_MODULE_ON_SLEEP)GetProcAddressA((HMODULE)m_hModule, STR_SleepAPI);
			m_moduleExitAPI = (EXT_MODULE_ON_SLEEP)GetProcAddressA((HMODULE)m_hModule, STR_ExitAPI);
			m_moduleWndProcAPI = (EXT_MODULE_WNDPROC)GetProcAddressA((HMODULE)m_hModule, STR_WndProccess);
#else
			m_moduleFreeAPI = (EXT_MODULE_FREE_PTR)GetProcAddress((HMODULE)m_hModule, STR_FreePtrAPI);
			m_moduleInitAPI = (EXT_MODULE_ON_INIT)GetProcAddress((HMODULE)m_hModule, STR_InitAPI);
			m_moduleSleepAPI = (EXT_MODULE_ON_SLEEP)GetProcAddress((HMODULE)m_hModule, STR_SleepAPI);
			m_moduleExitAPI = (EXT_MODULE_ON_SLEEP)GetProcAddress((HMODULE)m_hModule, STR_ExitAPI);
			m_moduleWndProcAPI = (EXT_MODULE_WNDPROC)GetProcAddress((HMODULE)m_hModule, STR_WndProccess);
#endif
			LoadAPI(apilist, apinum);

			if (m_moduleInitAPI)
			{
				m_moduleInitAPI(sendMessageSwf);
			}
			return true;
		}
		else
		{
			DWORD err =	GetLastError();
			printf("dynamicCodeLoaderwind32 loadmoder  --- error = %d\n  module=%s  path=%s \n", err, wpath,path);
		}
	}

	return false;
}


void *CDCodeLoader::CallAPI(char *func, char *params)
{
	if (m_apiHashTable)
	{
		struct HT_entry* entry = HT_table_lookup_entry((struct HT_table*)m_apiHashTable, func);
		if (entry)
		{
			EXT_API_Func apiAddr = (EXT_API_Func)entry->v;
			if (apiAddr)
			{
#if 0
				char *res = apiAddr(params);
				if (res)
				{
					char *dumpres = _strdup(res);
					if (m_moduleFreeAPI)
					{
						m_moduleFreeAPI(res);
					}
					return dumpres;
				}
#else
				return apiAddr(params);

#endif
			}
		}
	}
	return NULL;
}

void CDCodeLoader::WndProc(unsigned int message, unsigned long wParam, unsigned long lParam)
{
	if (m_moduleWndProcAPI)
	{
		m_moduleWndProcAPI(message, wParam, lParam);//20251458 0 132

	}
}
